Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add dummy WFI implementation #470

Merged
merged 1 commit into from
Aug 18, 2024
Merged

Add dummy WFI implementation #470

merged 1 commit into from
Aug 18, 2024

Conversation

ChinYikMing
Copy link
Collaborator

The Wait for Interrupt instruction (WFI) provides a hint to the implementation that the current hart can be stalled until an interrupt might need servicing. As well, Linux kernel might call wait_for_interrupt() to enter idle state. In this commit, we could simply make PC + 4 and not really enter idle state.

Related: #310

The Wait for Interrupt instruction (WFI) provides a hint to the
implementation that the current hart can be stalled until an
interrupt might need servicing. As well, Linux kernel might call
wait_for_interrupt() to enter idle state. In this commit, we
could simply make PC + 4 and not really enter idle state.

Related: sysprog21#310
@jserv jserv changed the title Add Wait for Interrupt instruction (WFI) Add dummy WFI implementation Jul 21, 2024
Copy link
Contributor

@jserv jserv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmarks

Benchmark suite Current: 8ac3c95 Previous: f2e41a8 Ratio
Dhrystone 1630.77 Average DMIPS over 10 runs 1589.12 Average DMIPS over 10 runs 0.97
Coremark 1490.998 Average iterations/sec over 10 runs 1402.631 Average iterations/sec over 10 runs 0.94

This comment was automatically generated by workflow using github-action-benchmark.

@jserv
Copy link
Contributor

jserv commented Jul 21, 2024

You should clarify WFI implementation. WFI is crucial for SMP awareness, and I did the following incomplete work for semu. (Linux only)

static uint64_t read_time(vm_t *vm)
{
    emu_state_t *data = (emu_state_t *) vm->priv;
    return data->time;
}

static void wfi(vm_t *vm)
{
    emu_state_t *data = (emu_state_t *) vm->priv;

    struct timespec start;
    clock_gettime(CLOCK_MONOTONIC, &start);

    struct pollfd pfd[] = {
        {data->timer_fd, 0, 0},
    };

    if (data->time < data->timer) {
        int64_t ticks = data->timer - data->time;
        ticks = (ticks * 1e9) / CLOCK_FREQ;
        struct itimerspec spec = {
            {0, 0},
            {ticks / (int64_t) 1e9, ticks % (int64_t) 1e9},
        };
        timerfd_settime(data->timer_fd, 0, &spec, NULL);
        pfd[0].events |= POLLIN;
    }

    while (!(vm->sip & vm->sie)) {
        int ret = poll(pfd, sizeof(pfd) / sizeof(*pfd), -1);
        assert(ret >= 0);
        if (pfd[0].revents & POLLIN) {
            vm->sip |= RV_INT_STI_BIT;
            pfd[0].events &= ~POLLIN;
        }
    }         

    struct timespec end;
    clock_gettime(CLOCK_MONOTONIC, &end);
    int64_t ticks =
        (end.tv_sec - start.tv_sec) * 1e9 + (end.tv_nsec - start.tv_nsec);
    data->time += (ticks * CLOCK_FREQ) / 1e9;
}

@jserv jserv merged commit 4ed6317 into sysprog21:master Aug 18, 2024
8 checks passed
@ChinYikMing ChinYikMing deleted the wfi branch August 18, 2024 12:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants